﻿//////////////////////////////////////////////////////////////////////////
//                                                                      //  
//  Eksponent CropUp (www.eksponent.com)                                //
//  Copyright(c) @nielskuhnel (Niels Kühnel, Eksponent). License: MIT.  //
//                                                                      //
//////////////////////////////////////////////////////////////////////////


var CropUpEditor = (function ($) {

    var image, croppings, dataField;

    var _this;
    $.fn.cropUpEditor = function (options) {

        if ($(this).length > 1) {
            $(this).each(function () {
                $(this).cropUpEditor();
            });
            return;
        }

        target = $(this);
        options = options || {};

        if (target.is("input")) {
            var input = target;
            target = $("<div class='crop-up-editor'></div>").insertBefore(target);
            target.append(input);
            target.cropUpEditor(options);
            return;
        } else {
            target.addClass("crop-up-editor");
        }

        var dataField = $("input", target);

        var biasHandle;

        var img = $(options.selector || "img", target);
        if (!img.length) {
            img = $("<img />").attr("src", options.src).appendTo(target);
        }

        if (!$(target).is(":visible")) {
            setTimeout(function () { target.cropUpEditor(options); }, 50);
            return;
        }



        CropUp.measureImage(img[0], img.attr("src"), function (width, height) {

            var jcrop;

            var value = dataField.val();

            var data = value ? JSON.parse(value) : {
                "default": {
                    box: [0, 0, 1, 1],
                    gravity: [.5, .5]
                },

                croppings: []
            };

            data.croppings = data.croppings || {};

            var cropping = data["default"];
            var cropDefinition = null;

            var hasCroppings = false;
            if (options.croppings) for (var s in options.croppings) { hasCroppings = true; break; }

            //Create menu for manual croppings
            if (hasCroppings) {
                var ul = $("<ul class='croppings' />").appendTo(target);
                var li = $("<li class='default selected' />").attr("data-alias", "default").append($("<span />").text("Default")).appendTo(ul);

                var li = $("<li class='header' />").attr("data-alias", "").append($("<span />").text("Manual croppings")).appendTo(ul);

                for (var s in options.croppings) {
                    var o = options.croppings[s];
                    var li = $("<li class='manual' />").attr("data-alias", s).append($("<span />").text(o.label || s))
						.append("<a href='#' style='display:none' class='reset'>Reset</a>")
						.data("definition", o)
						.appendTo(ul);

                    o.aspect = o.width / o.height;

                    if (!data.croppings[s]) {
                        data.croppings[s] = {};
                    }
                }

                $("li", ul).click(function () {
                    var li = $(this);
                    var alias = li.data("alias");
                    if (alias) {
                        $("li", ul).removeClass("selected");
                        li.addClass("selected");
                        cropDefinition = options.croppings[alias];
                        cropping = alias == "default" ? data["default"] : data.croppings[alias];

                        loadData();
                        updateManualCroppings();
                    }
                });

                $("li a.reset", ul).click(function () {
                    data.croppings[$(this).parent().data("alias")].manual = false;
                    updateManualCroppings();
                });



                ul.position({ my: "left top", at: "right top", of: img, collision: "none" });
            }





            var changing = false;
            img.Jcrop({
                keySupport: false,
                onChange: function (c) { biasHandle.fade(c); },
                onSelect: function (c) {
                    setCropData(c);
                    if (!changing) saveData();
                    else changing = false;
                },
                onRelease: function (c) {
                    setCropData(null);
                    if (!changing) saveData();
                    else changing = false;
                },
                swingSpeed: 2
            }, function () {
                jcrop = this;
                biasHandle.attach(img);
                loadData();
            });

            function setCropData(c) {

                biasHandle.update(c);

                if (cropping != data["default"]) {
                    cropping.manual = true;
                }

                var w = img.width();
                var h = img.height();

                if (c == null) {
                    var cur = cropping.box;
                    cropping.manual = false;

                    if (!(cur && cur[0] == 0 && cur[1] == 0 && cur[2] == 1 && cur[3] == 1)) {
                        cropping.box = [0, 0, 1, 1];
                        if (cropping != data["default"]) {
                            updateManualCroppings();
                            loadData();
                        }
                    }
                } else {
                    c = [c.x, c.y, c.x2, c.y2];
                    cropping.box = [c[0] / w, c[1] / h, c[2] / w, c[3] / h];
                }
            }

            function loadData(now) {
                var w = img.width();
                var h = img.height();

                var c = cropping.box;
                if (cropping.gravity) {
                    biasHandle.show(true);
                    biasHandle.setCoords(w * cropping.gravity[0], h * cropping.gravity[1]);
                    biasHandle.update({ x: c[0] * w, y: c[1] * h, x2: c[2] * w, y2: c[3] * h });

                } else {
                    biasHandle.hide();
                }

                changing = true;

                jcrop.setOptions({ aspectRatio: cropDefinition ? cropDefinition.aspect : null });

                if (Math.round((c[2] - c[0]) * w) == w && Math.round((c[3] - c[1]) * h) == h) {
                    jcrop.release();
                } else {
                    if (now) jcrop.setSelect([c[0] * w, c[1] * h, c[2] * w, c[3] * h]);
                    else jcrop.animateTo([c[0] * w, c[1] * h, c[2] * w, c[3] * h]);
                }
                changing = false;
            }


            var toUpdateCallback;
            function saveData() {
                updateManualCroppings();

                $(dataField).val(JSON.stringify(data));

                clearTimeout(toUpdateCallback);
                toUpdateCallback = setTimeout(function () {
                    if (options.update) options.update(data);
                }, 1);
            }


            biasHandle = (function () {

                var handle = $("<div class='bias-handle'></div>");
                var isFaded = false;

                var _this;
                var visible = true;
                return _this = {
                    onChange: function () {
                    },

                    //Target image is a image with jCrop applied
                    attach: function (targetImage) {
                        var target = $(targetImage).next(".jcrop-holder");

                        handle.appendTo(target).position({ my: "center", at: "center", of: target }).draggable({
                            stop: function () { if (_this.onChange) _this.onChange(_this.getCoords()); }
                        });
                    },

                    getCoords: function () {
                        var pos = handle.offset();
                        var parentPos = handle.parent().offset();

                        pos.left -= parentPos.left;
                        pos.top -= parentPos.top;

                        pos.left += Math.round(handle.width() / 2);
                        pos.top += Math.round(handle.height() / 2);

                        return pos;
                    },

                    setCoords: function (x, y) {
                        x -= Math.round(handle.width() / 2);
                        y -= Math.round(handle.height() / 2);

                        handle.css({ left: x + "px", top: y + "px" });
                    },

                    show: function (now) {
                        visible = true;
                        handle.fadeIn(now ? 0 : 100);
                    },

                    hide: function (now) {
                        visible = false;
                        handle.fadeOut(now ? 0 : 100);
                    },

                    isVisible: function () {
                        return visible;
                    },

                    fade: function (coords) {
                        if (!_this.isVisible()) {
                            return;
                        }

                        var c = this.getCoords();
                        if (c.left < coords.x || c.left > coords.x2 || c.top < coords.y || c.top > coords.y2) {
                            if (!isFaded) {
                                handle.stop().animate({ opacity: .2 }, { duration: 300 });
                                isFaded = true;
                            }
                        } else {
                            if (isFaded) {
                                handle.stop().animate({ opacity: 1 }, { duration: 300 });
                                isFaded = false;
                            }
                        }
                    },

                    update: function (coords) {

                        if (!_this.isVisible()) {
                            return;
                        }

                        var c = this.getCoords();

                        isFaded = false;

                        //Center displacements
                        var wd = Math.round(handle.width() / 2);
                        var hd = Math.round(handle.height() / 2);
                        var offset = handle.parent().offset();

                        if (coords != null) {
                            if (c.left < coords.x || c.left > coords.x2 || c.top < coords.y || c.top > coords.y2) {

                                handle.stop().animate({
                                    opacity: 1,
                                    top: Math.round(coords.y + (coords.y2 - coords.y) / 2) - handle.height() / 2,
                                    left: Math.round(coords.x + (coords.x2 - coords.x) / 2) - handle.width() / 2
                                }, {
                                    duration: 200,
                                    complete: function () {
                                        if (_this.onChange) _this.onChange(_this.getCoords());
                                    }
                                });
                            } else {
                                handle.stop().animate({ opacity: 1 }, { duration: 100 });
                            }
                            handle.draggable("option", "containment", [coords.x + offset.left - wd, coords.y + offset.top - hd, coords.x2 + offset.left - wd, coords.y2 + offset.top - hd]);
                        } else {
                            handle.stop().animate({ opacity: 1 }, { duration: 100 });
                            handle.draggable("option", "containment", [offset.left - wd, offset.top - hd, offset.left + handle.parent().width() - wd,
								offset.top + handle.parent().height() - hd]);

                            //if (_this.onChange) _this.onChange(c);
                        }
                    }
                };
            })();


            biasHandle.onChange = function (c) {
                var w = img.width();
                var h = img.height();

                cropping.gravity = [c.left / w, c.top / h];
                saveData();
            };

            function updateManualCroppings() {
                if (hasCroppings) {
                    var w = options.originalWidth || img.width(), h = options.originalHeight || img.height();

                    var info = {
                        topLeft: [w * data["default"].box[0], h * data["default"].box[1]],
                        bottomRight: [w * data["default"].box[2], h * data["default"].box[3]],
                        bias: [w * data["default"].gravity[0], h * data["default"].gravity[1]],
                        calculated: true
                    };

                    $("li.manual", ul).each(function () {
                        var s = $(this).data("alias");
                        var d = options.croppings[s];
                        var c = data.croppings[s];
                        if (!c.manual) {
                            $(this).removeClass("overriden").find("a").stop().hide();
                            var sugg = CropUp.suggest(w, h, d.width, d.height, info);

                            c.box = [sugg.topLeft[0] / w, sugg.topLeft[1] / h,
								sugg.bottomRight[0] / w, sugg.bottomRight[1] / h];
                        } else {
                            $(this).addClass("overriden");
                            if ($(this).is(".selected")) {
                                $("a", this).stop().fadeIn(300);
                            } else {
                                $("a", this).stop().hide();
                            }
                        }
                    });
                }
            }

            updateManualCroppings();

        });
    };
})(jQuery);